//
//  NSObject+DF.m
//  微商社区
//
//  Created by nahuo on 15/1/8.
//  Copyright (c) 2015年 nahuo. All rights reserved.
//

#import "NSObject+DF.h"
#import "DFRuntime.h"


@implementation NSObject (DF)




+(NSArray *)objectArrayWithKeyValuesArray:(NSArray *)keyValuesArray {
    if(![keyValuesArray isKindOfClass:[NSArray class]] || !keyValuesArray.count) {
        return nil;
    }
    NSMutableArray* objectArray = [NSMutableArray arrayWithCapacity:keyValuesArray.count];
    for (id keyValues in keyValuesArray) {
        [objectArray addObject:[self objectWithKeyValues:keyValues]];
    }
    return objectArray;
}

+(instancetype)objectWithKeyValues:(NSDictionary *)keyValues {
    id obj = [self new];
    [obj setKeyValues:keyValues];
    return obj;
}


-(void)setKeyValues:(NSDictionary *)keyValues {
    [self setKeyValues:keyValues keyMapping:nil];
}

-(void)setKeyValues:(NSDictionary *)keyValues keyMapping:(NSDictionary *)keyMapping {
    if(![keyValues isKindOfClass:[NSDictionary class]]  || !keyValues.count) {
        return;
    }
    for(NSString* key in keyValues) {
        NSString* name = key;
        if(keyMapping) {
            name = keyMapping[key];
            if(!name) {
                continue;
            }
        }
        SEL sel = [self selectorForSetterFromName:name];
        if ([self respondsToSelector:sel]) {
            id value = keyValues[key];
            if([value isKindOfClass:[NSDictionary class]]) {
                NSString* className = [self classNameWithPropertyName:name];
                Class class = NSClassFromString(className);
                value = [class objectWithKeyValues:value];
                [self performSelectorOnMainThread:sel
                                       withObject:value
                                    waitUntilDone:YES];
            }else {
                [self performSelectorOnMainThread:sel
                                       withObject:value
                                    waitUntilDone:YES];
            }

        }
    }
}

- (NSString*)classNameWithPropertyName:(NSString*)propertyName {
    objc_property_t property = class_getProperty([self class], [propertyName UTF8String]);
    //NSString* type = [NSString stringWithUTF8String:property_getAttributes(property)];
    //MyLog(@"%@",type);
    unsigned int outCount = 0;
    objc_property_attribute_t * attributes = property_copyAttributeList(property,&outCount);
    for (int i=0; i<outCount; i++) {
        objc_property_attribute_t attribute = attributes[i];
        if([@"T" isEqualToString:[NSString stringWithUTF8String:attribute.name]]) {
            NSString* name = [NSString stringWithUTF8String:attribute.value];
            return [name substringWithRange:NSMakeRange(2, name.length-3)];
        }
        free(attributes);
    }
    return nil;
}

-(NSDictionary *)keyValues {
    return nil;
}



- (SEL)selectorForSetterFromName:(NSString*)name {
    return NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",[[name substringToIndex:1] uppercaseString],[name substringFromIndex:1]]);
}


#pragma mark RunTime
+(NSArray *)classes {
    NSMutableArray* classes = [NSMutableArray array];
    // 3.当前正在遍历的类
    Class class = [self class];
    // 4.开始遍历每一个类
    while (class) {
        [classes addObject:class];
        // 4.2.获得父类
        class = class_getSuperclass(class);
    }
    return classes;
}


+ (NSArray *)ivars {
    
    NSArray* classes = [self classes];
    NSMutableArray* ivars = [NSMutableArray array];
  
    for (Class class in classes) {
        // 1.获得所有的成员变量
        unsigned int outCount = 0;
        
        Ivar *ivarList = class_copyIvarList(class, &outCount);
        
        // 2.遍历每一个成员变量
        for (unsigned int i = 0; i<outCount; i++) {
            //[ivars addObject:ivars[i]];
            [ivars addObject: [[DFIvar alloc] initWithIvar:ivarList[i]]];
        }
        
        // 3.释放内存
        free(ivarList);
    }
    
    return ivars;

}





- (void)encodeWithCoder:(NSCoder *)encoder  {
    NSArray* ivars  = [self.class ivars];
    for (DFIvar* ivar in ivars) {
        if(ivar.type) {
            id value = [ivar valueForObject:self];
            [encoder encodeObject:value forKey:ivar.propertyName];
        }
    }
    
}



- (id)initWithCoder:(NSCoder *)decoder
{
    if(self = [self init]) {
        NSArray* ivars  = [self.class ivars];
        for (DFIvar* ivar in ivars) {
            if(ivar.type) {
                id value = [decoder decodeObjectForKey:ivar.propertyName];
                [ivar setValue:value forObject:self];
            }
        }
    }
    return self;
}



@end
